﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MS.InformationManagement.Support;
using Microsoft.SharePoint;
using MS.InformationManagement.DAL.DocumentCenter;
using MS.InformationManagement.Support.Constants;
using MS.InformationManagement.Core.RecordSiteQuery;
using System.Web.UI.WebControls;
using MS.InformationManagement.BLL.UserProfileManagement;
using Microsoft.SharePoint.Linq;
using MS.InformationManagement.DAL.RecordCenter;
using RecordsDC = MS.InformationManagement.DAL.RecordCenter;
using Microsoft.SharePoint.Taxonomy;

namespace MS.InformationManagement.BLL.GestionDeUsuarios
{
    public class GestionDeUsuariosBLL
    {

        #region fields

        #endregion


        public string getProperty(string propertyNamme, string Login)
        {
            return PeopleHelper.GetPropertyUserProfile(propertyNamme, Login);
        }

        public bool updatePropertys(SPUser User, string CedulaUsuario, string TelefonoUsuario,
            string UbicacionUsuario, string DepartamentoUsuario, string UserPerfil, string Observacion)
        {
            bool succeed = false;
            string currentUser = SPContext.Current.Web.CurrentUser.Name;
            ExistUserID(User.LoginName, CedulaUsuario);
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Web.Url))
                {
                    using (SPWeb miWeb = site.OpenWeb())
                    {
                        site.AllowUnsafeUpdates = true;
                        miWeb.AllowUnsafeUpdates = true;

                        List<LogDeUsuario> newLogs = new List<LogDeUsuario>();
                        string currentDepartment = getProperty(GlobalConstants.UP_DEPARTMENT, User.LoginName);
                        string currentUserProfile = getProperty(GlobalConstants.UP_USER_PERFIL, User.LoginName);
                        string currentLocation = getProperty(GlobalConstants.UP_OFFICE_lOCATION, User.LoginName);

                        DateTime currentDateTime = DateTime.Now;


                        if (!currentLocation.Equals(UbicacionUsuario))
                        {
                            newLogs.Add(new LogDeUsuario
                            {
                                Departamento = currentDepartment,
                                FechaOperación = currentDateTime,
                                PerfilUsuario = currentUserProfile,
                                Title = string.Empty,
                                UsuarioId = User.ID,
                                UsuarioAdministrador = currentUser,
                                Observaciones = Observacion,
                                Cambio = string.Format("Cambio de ubicación de {0} a {1}", currentLocation, UbicacionUsuario)
                            });
                        }

                        if (!currentDepartment.Equals(DepartamentoUsuario))
                        {
                            newLogs.Add(new LogDeUsuario
                            {
                                Departamento = currentDepartment,
                                FechaOperación = currentDateTime,
                                PerfilUsuario = currentUserProfile,
                                Title = string.Empty,
                                UsuarioId = User.ID,
                                UsuarioAdministrador = currentUser,
                                Observaciones = Observacion,
                                Cambio = string.Format("Cambio de dependencia de {0} a {1}", currentDepartment, DepartamentoUsuario)
                            });

                            setSectionPermissions(DepartamentoUsuario, User.LoginName, currentDepartment);
                        }

                        if (!currentUserProfile.Equals(UserPerfil))
                        {
                            newLogs.Add(new LogDeUsuario
                            {
                                Departamento = currentDepartment,
                                FechaOperación = currentDateTime,
                                PerfilUsuario = currentUserProfile,
                                Title = string.Empty,
                                UsuarioId = User.ID,
                                UsuarioAdministrador = currentUser,
                                Observaciones = Observacion,
                                Cambio = string.Format("Cambio de perfil de {0} a {1}", currentUserProfile, UserPerfil)
                            });

                            //Setting permissions
                            removeRolePermissions(User.LoginName, currentUserProfile);
                            setRolePermissions(User.LoginName, UserPerfil);
                        }

                        if (PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_CEDULA, CedulaUsuario, User.LoginName) != true) { succeed = false; }
                        if (PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_WORK_PHONE, TelefonoUsuario, User.LoginName) != true) { succeed = false; }
                        if (PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_OFFICE_lOCATION, UbicacionUsuario, User.LoginName) != true) { succeed = false; }
                        if (PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_DEPARTMENT, DepartamentoUsuario, User.LoginName) != true) { succeed = false; }
                        if (PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_USER_PERFIL, UserPerfil, User.LoginName) != true) { succeed = false; }

                        //Create library from user
                        string userName = User.LoginName;
                        string libraryName = userName.Substring(userName.LastIndexOf('\\') + 1);
                        SPList targetLibrary = SPContext.Current.Web.Lists.TryGetList(libraryName);

                        if (targetLibrary == null)
                        {
                            SPFieldUserValue uservalue = new SPFieldUserValue(miWeb, User.ID, User.LoginName);
                            Guid libraryUser = MS.InformationManagement.Core.SystemUser.UsersManager.CreateDocumentLibrary(uservalue);
                            MS.InformationManagement.Core.SystemUser.UsersManager.SetNewUserPermissions(uservalue, libraryUser);
                            targetLibrary = SPContext.Current.Web.Lists.TryGetList(libraryName);
                            newLogs.Add(new LogDeUsuario
                            {
                                Departamento = DepartamentoUsuario,
                                FechaOperación = currentDateTime,
                                PerfilUsuario = UserPerfil,
                                Title = string.Empty,
                                UsuarioId = User.ID,
                                UsuarioAdministrador = currentUser,
                                Observaciones = Observacion,
                                Cambio = string.Format("Creacion de usuario {0}", User)
                            });

                            //Set permissions
                            setRolePermissions(User.LoginName, UserPerfil);
                        }
                        
                        if (newLogs.Count > 0)
                        {
                            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(miWeb.Url))
                            {
                                ctx.LogsDeCambiosDeUsuario.InsertAllOnSubmit(newLogs);
                                ctx.SubmitChanges();
                            }
                        }
                        new MS.InformationManagement.Core.AdministracionDeUsuarios.AdministracionDeUsuarios().BreakPermissionLibrary(targetLibrary.ID);
                        new MS.InformationManagement.Core.AdministracionDeUsuarios.AdministracionDeUsuarios().AddPermissionLibrary(targetLibrary.ID, DepartamentoUsuario);

                        
                        /* 
                         * Adds the current user to the visitor group in order to give him read-only privileges on some lists that requiere access to all site users
                         */
                        SPGroup siteReadersGroup = miWeb.AssociatedVisitorGroup;
                        siteReadersGroup.AddUser(User);
                        siteReadersGroup.Update();
                        //Add user to group 
                        SPGroup spGroupCurrent = miWeb.Groups[DepartamentoUsuario];
                        if (spGroupCurrent != null)
                            spGroupCurrent.AddUser(User);

                        if (isPerfilSiteContributor(UserPerfil))
                            miWeb.Groups[GlobalConstants.GRP_GLOBAL_CONTRIBUTORS].AddUser(User);
                        else
                            miWeb.Groups[GlobalConstants.GRP_GLOBAL_CONTRIBUTORS].RemoveUser(User);

                        succeed = true;
                        miWeb.AllowUnsafeUpdates = false;
                    }
                }

            });

            return succeed;
        }


        #region private methods
        private static void ExistUserID(string LoginName, string newCedula)
        {
            string Mensaje = "El numero de cedula ya se encuentra asignado a otro usuario.";
            Dictionary<string, string> users = PeopleHelper.GetUsersByProperty(GlobalConstants.UP_CEDULA, newCedula, true);

            var UserByID = (from contacto in users
                            where contacto.Key.ToUpper() != LoginName.ToUpper()
                            select contacto);
            if (UserByID != null)
            {
                if (UserByID.Count() > 0)
                {
                    foreach (var entry in UserByID)
                    {
                        Mensaje += " " + entry.Value.GetUserWithOutDomain() + ".";
                    }

                    throw new Exception(Mensaje);
                }
            }
        }

        #endregion  


        private void removeRolePermissions(string login, string perfil)
        {
            RemoveUserRolePermissionsCommand removeCommand = new RemoveUserRolePermissionsCommand(login, perfil);
            removeCommand.Execute();
        }

        private void setRolePermissions(string login, string perfil)
        {
            SetUserRolePermissionsCommand setCommand = new SetUserRolePermissionsCommand(login, perfil);
            setCommand.Execute();
        }

        private void setSectionPermissions(string newDepartment, string login, string oldDepartment)
        {
            var allowedSections = GetAllowedSeccionsCurrentUser(login, newDepartment);
            var oldsections = GetAllowedSeccionsCurrentUser(login, oldDepartment);

            if (oldsections != null)
            {
                RemoveUserGroupCommand removeGrupsPermissions = new RemoveUserGroupCommand(login, oldsections);
                removeGrupsPermissions.Execute();
            }

            if (allowedSections != null)
            {
                AddUserGroupCommand updatePermissions = new AddUserGroupCommand(login, allowedSections);
                updatePermissions.Execute();
            }
        }

        public List<VincularPerfiles> GetPerfiles()
        {
            using (var dx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                List<VincularPerfiles> listPerfiles = dx.GetList<VincularPerfiles>(GlobalConstants.LIST_PERFILES_ROL).ToList();
                return listPerfiles;
            }
        }

        public static bool GetLibrary(SPUser User)
        {
            bool result = false;
            string userName = User.LoginName;
            string libraryName = userName.Substring(userName.LastIndexOf('\\') + 1);
            SPList targetLibrary = SPContext.Current.Web.Lists.TryGetList(libraryName);
            if (targetLibrary != null)
            {
                result = true;
            }

            return result;
        }

        public static List<Roles> LoadRolesProfile(int IdPerfil)
        {
            List<Roles> rolesList = new List<Roles>();

            DAL.DocumentCenter.VincularPerfiles loadedProfile = UserProfileCreationBLL.GetProfile(IdPerfil);
            if (loadedProfile != default(DAL.DocumentCenter.VincularPerfiles))
            {
                rolesList = loadedProfile.TipoRole.ToList();
            }

            return rolesList;
        }

        public static int GetIdPerfilByName(string PerfilName)
        {
            using (var dx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var perfil = (from contacto in dx.Perfiles
                              where contacto.Perfil == PerfilName
                              select contacto).FirstOrDefault();

                if (perfil != null)
                    return int.Parse(perfil.Id.ToString());
                else
                    return 0;
            }
        }

        public static IEnumerable<LogDeUsuario> GetUserChanges(int userID)
        {
            IEnumerable<LogDeUsuario> foundElements = null;
            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                foundElements = (from logEntry in ctx.LogsDeCambiosDeUsuario
                                 orderby logEntry.FechaOperación
                                 where logEntry.UsuarioId.Equals(userID)
                                 select logEntry);
            }
            return foundElements;
        }

        private static bool isPerfilSiteContributor(string perfilName)
        {
            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var perfil = (from per in dc.Perfiles
                              where per.Perfil == perfilName
                              select per).FirstOrDefault();
                return perfil == null || !perfil.ContribuyenteEnSitio.HasValue ? false : perfil.ContribuyenteEnSitio.Value;
            }
        }


        private IEnumerable<Seccion> AllowedSeccions(string userDepartment)
        {
            using (var dc = new RecordsDC.DataContext(SPContext.Current.Web.Url))
            {
                int? deptoId = (from depto in dc.Secciones
                                where depto.Title == userDepartment
                                select depto.Id).FirstOrDefault();
                if (!deptoId.HasValue)
                    return null;

                var allowedSeccions = (from depto in dc.Secciones
                                       where (depto.SecciónPadre.Id == deptoId) ||
                                             (depto.Id == deptoId)
                                       select new Seccion
                                       {
                                           Id = depto.Id,
                                           Title = depto.Title, 
                                           Grupo = depto.Grupo
                                         
                                       });
                return allowedSeccions;
            }
        }


        private IEnumerable<Seccion> AllowedSeccions()
        {
            string userDepartment = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_DEPARTMENT);
            using (var dc = new RecordsDC.DataContext(SPContext.Current.Web.Url))
            {
                int? deptoId = (from depto in dc.Secciones
                                where depto.Title == userDepartment
                                select depto.Id).FirstOrDefault();
                if (!deptoId.HasValue)
                    throw new Exception("El departamento del usuario es invalido");
                var allowedSeccions = (from depto in dc.Secciones
                                       where (depto.SecciónPadre.Id == deptoId) ||
                                             (depto.Id == deptoId)
                                       select new Seccion
                                       {
                                           Id = depto.Id,
                                           Title = depto.Title
                                       });
                return allowedSeccions;
            }
        }

        private IEnumerable<Seccion> AllowedSeccions(int selectedDepartment)
        {
            string userDepartment = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_DEPARTMENT);
            using (var dc = new RecordsDC.DataContext(SPContext.Current.Web.Url))
            {
                int? deptoId = (from depto in dc.Secciones
                                where depto.Title == userDepartment
                                select depto.Id).FirstOrDefault();
                if (!deptoId.HasValue)
                    throw new Exception("El departamento del usuario es invalido");
                var allowedSeccions = (from depto in dc.Secciones
                                       where (depto.SecciónPadre.Id == deptoId) ||
                                             (depto.Id == deptoId) ||
                                             (depto.Id == selectedDepartment)
                                       select new Seccion
                                       {
                                           Id = depto.Id,
                                           Title = depto.Title
                                       });
                return allowedSeccions;
            }
        }

        private IEnumerable<Seccion> AllSeccions()
        {
            using (var dc = new RecordsDC.DataContext(SPContext.Current.Web.Url))
            {
                var allSecciones = from seccion in dc.Secciones
                                   select new Seccion()
                                   {
                                      Id = seccion.Id,
                                      Grupo = seccion.Grupo,
                                      Title = seccion.Title
                                   };
                return allSecciones;
            }
        }

        public IEnumerable<Seccion> GetAllowedSeccionsCurrentUser(string targetUser, string currentDepartment)
        {
            bool showAll = false;
            string currentUserProfile = PeopleHelper.GetPropertyUserProfile(GlobalConstants.UP_USER_PERFIL, targetUser);

            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var showAllDepartments = (from profile in dc.Perfiles
                                          where profile.Perfil == currentUserProfile &&
                                                profile.ContribuyenteEnSitio == true
                                          select profile).FirstOrDefault();
                showAll = showAllDepartments != null;
            }

            return showAll ? AllSeccions() : AllowedSeccions(currentDepartment);
        }


        public IEnumerable<Seccion> GetAllowedSeccionsCurrentUser(string targetUser)
        {
            bool showAll = false;
            string currentUserProfile = PeopleHelper.GetPropertyUserProfile(GlobalConstants.UP_USER_PERFIL, targetUser);

            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var showAllDepartments = (from profile in dc.Perfiles
                                          where profile.Perfil == currentUserProfile &&
                                                profile.ContribuyenteEnSitio == true
                                          select profile).FirstOrDefault();
                showAll = showAllDepartments != null;
            }

            return showAll ? AllSeccions() : AllowedSeccions();
        }


        public IEnumerable<Seccion> GetAllowedSeccionsCurrentUser()
        {
            bool showAll = false;
            string currentUserProfile = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_USER_PERFIL);

            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var showAllDepartments = (from profile in dc.Perfiles
                                          where profile.Perfil == currentUserProfile &&
                                                profile.ContribuyenteEnSitio == true
                                          select profile).FirstOrDefault();
                showAll = showAllDepartments != null;
            }

            return showAll ? AllSeccions() : AllowedSeccions();
        }

        public IEnumerable<Seccion> GetAllowedSeccionsCurrentUser(int selectedDepartment)
        {
            bool showAll = false;
            string currentUserProfile = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_USER_PERFIL);

            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var showAllDepartments = (from profile in dc.Perfiles
                                          where profile.Perfil == currentUserProfile &&
                                                profile.ContribuyenteEnSitio == true
                                          select profile).FirstOrDefault();
                showAll = showAllDepartments != null;
            }

            return showAll ? AllSeccions() : AllowedSeccions(selectedDepartment);
        }


    }
}
